﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Traders.Controllers;
using Traders.Views;

namespace Traders.Models
{
    class BalanceModel : TradersModel
    {
        #region Podstawowe inicjalizacje z interfejsu TradersModel
        
        private DataColumn[] _columns = {
                                new DataColumn("Broker", typeof(string)),
                                new DataColumn("Account", typeof(string)),
                                new DataColumn("Balance", typeof(double)),
                                new DataColumn("Equity", typeof(double)),
                                new DataColumn("Currency", typeof(string)),
                                new DataColumn("Free Margin", typeof(double))
                                };

        private DataColumn getColumn(string Name)
        {
            var column =
                from c in _columns
                where c.ColumnName == Name
                select c;
            
            return column.First();
        }

        public DataColumn[] DataColumns { get { return _columns; } }
        
        private bool _initialized = false;
        public Boolean Initialized { get { return _initialized; } }

        private DataTable _dataTable = new DataTable();
        public DataTable DataTable
        {
            get { return _dataTable; }
        } 

        #endregion

        private AccountManager AccountManager { get; set; }
        
        public BalanceModel(AccountManager accounts)
        {
            this.AccountManager = accounts;
            foreach (var c in _columns) _dataTable.Columns.Add(c);
            DataColumn[] PrimaryKeys = { getColumn("Broker"), getColumn("Account") };
            _dataTable.PrimaryKey = PrimaryKeys;
        }

        public void doTicks(int miliseconds)
        {
            switch (miliseconds)
            {
                case 1000:
                    refreshAccounts();
                    break;
            }
        }

        private void refreshAccounts()
        {
            if (!_initialized) return;

            foreach (Account a in AccountManager.Accounts)
            {
                object[] keys = { a.Broker, a.Login };
                DataRow row = _dataTable.Rows.Find(keys);
                row.SetField(getColumn("Balance"), a.Strategy.AccountBalance());
                row.SetField(getColumn("Equity"), a.Strategy.AccountEquity());
                row.SetField(getColumn("Free Margin"), a.Strategy.AccountFreeMargin());
            }
            
        }

        #region Inicjalizacje eventów z interfejsu

        public event EventHandler<TradersEventArgs> EventHandler;

        public void FireEvent(TradersEventArgs e)
        {
            if (EventHandler != null)
                EventHandler(this, e);
        }

        public void HandleEvent(object sender, TradersEventArgs e)
        {
            switch (e.Action)
            {
                case "AddAccountClicked":
                    if (e.Tag is Account) { ConnectAccount((Account)e.Tag); }
                    else throw new Exception("Źle wywołana metoda ConnectAccount - błędny parametr Tag.");
                    break;
                case "AccountConnected":
                    if (e.Tag is Account) { AddAccount((Account)e.Tag); }
                    else throw new Exception("Źle wywołana metoda AddAccount - błędny parametr Tag.");
                    break;
                case "ConnectionSuccess":
                    _initialized = true;
                    break;
            }
        }

        #endregion

        #region Metody z eventów

        private void ConnectAccount(Account a)
        {
            this.AccountManager.ConnectAccount(a);
        }

        private void AddAccount(Account a)
        {
            string broker = a.Broker;
            string login = a.Login;
            double balance = a.Strategy.AccountBalance();
            double equity = a.Strategy.AccountEquity();


            _dataTable.Rows.Add(broker, login, balance, equity, a.Strategy.AccountCurrency(), a.Strategy.AccountFreeMargin());
            TradersEventArgs e = new TradersEventArgs();
            e.Action = "AccountAdded";
            e.Tag = a;
            FireEvent(e);
        }

        #endregion



        
    }
}
